package net.organizer.dao;

import javax.persistence.Id;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.appengine.api.datastore.Entity;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.annotation.Parent;


public class Person {
	protected long    addressId;
	protected Long  dateOfBirth;
	protected String  firstName;
	protected String  googleUserId;
	@Id protected Long   id;
	protected String  lastName;
	protected String  phoneNumberCell;
	protected String  phoneNumberHome;
	protected String  phoneNumberOffice;
	protected Long version = 1L;

	@Parent protected Key<Domain> domainKey;
	@Transient protected Domain domain;
	
	/**
	 * returns key with domain parent entity reference
	 * @return
	 */
	public Key<Person> getKey(){
		if(this.domainKey==null){
			throw new UnsupportedOperationException(String.format("attempt to getKey with null instance domain... person: %s", this));
		}
		return new Key<Person>(domainKey, Person.class, this.getId());
	}

	public static Key<Person> getKey(Domain domain, Long id){
		return new Key<Person>(domain.getKey(), Person.class, id);
	}
	public Key<Domain> getDomainKey() {
		return domainKey;
	}

	public void setDomainKey(Key<Domain> domainKey) {
		this.domainKey = domainKey;
	}

	public Domain getDomain() {
		return domain;
	}

	public void setDomain(Domain domain) {
		this.domain = domain;
	}

	public Person() {
		super();
	}

	public JSONObject toJSONObject() {
		  JSONObject result = new JSONObject();
		  try {
			result.put("addressId", this.getAddressId());
			result.put("id", this.getId());
			result.put("firstName", this.getFirstName());
			result.put("googleUserId", this.getGoogleUserId());
			result.put("lastName", this.getLastName());
			result.put("id", this.getId());
			result.put("phoneNumberCell", this.getPhoneNumberCell());
			result.put("phoneNumberHome", this.getPhoneNumberHome());
			result.put("phoneNumberOffice", this.getPhoneNumberOffice());
			result.put("dateOfBirth", this.getDateOfBirth());
			result.put("version", this.getVersion());
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
		return result;
	}
	public Person(Long version, long addressId, Long dateOfBirth, Domain domain, String firstName, String googleUserId,
			String lastName, String phoneNumberCell, String phoneNumberHome, String phoneNumberOffice) {
		super();
		this.version = version;
		this.addressId = addressId;
		this.dateOfBirth = dateOfBirth;
		this.firstName = firstName;
		this.googleUserId = googleUserId;
		this.lastName = lastName;
		this.phoneNumberCell = phoneNumberCell;
		this.phoneNumberHome = phoneNumberHome;
		this.phoneNumberOffice = phoneNumberOffice;
		this.domainKey =  domain.getKey();
	}
	public long getAddressId() {
		return addressId;
	}
	public Long getDateOfBirth() {
		return dateOfBirth;
	}
	public String getFirstName() {
		return firstName;
	}
	public String getGoogleUserId() {
		return googleUserId;
	}
	public Long getId() {
		return id;
	}
	public String getLastName() {
		return lastName;
	}
	public String getPhoneNumberCell() {
		return phoneNumberCell;
	}
	public String getPhoneNumberHome() {
		return phoneNumberHome;
	}
	public String getPhoneNumberOffice() {
		return phoneNumberOffice;
	}
	public Long getVersion() {
		return version;
	}
	public void setAddressId(long addressId) {
		this.addressId = addressId;
	}
	public void setDateOfBirth(Long dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public void setGoogleUserId(String googleUserId) {
		this.googleUserId = googleUserId;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public void setPhoneNumberCell(String phoneNumberCell) {
		this.phoneNumberCell = phoneNumberCell;
	}
	public void setPhoneNumberHome(String phoneNumberHome) {
		this.phoneNumberHome = phoneNumberHome;
	}
	public void setPhoneNumberOffice(String phoneNumberOffice) {
		this.phoneNumberOffice = phoneNumberOffice;
	}
	public void setVersion(Long version) {
		this.version = version;
	}
	@Override
	public String toString() {
		return "Person [addressId=" + addressId + ", dateOfBirth=" + dateOfBirth + ", firstName=" + firstName
				+ ", googleUserId=" + googleUserId + ", id=" + id + ", lastName=" + lastName + ", phoneNumberCell="
				+ phoneNumberCell + ", phoneNumberHome=" + phoneNumberHome + ", phoneNumberOffice=" + phoneNumberOffice
				+ ", version=" + version + ", domainKey=" + domainKey + ", domain=" + domain + "]";
	}

	@PostLoad void postLoad(Objectify ofy, Entity entity){
		//logger.fine(String.format("postLoad... entity: %s", entity));
		this.verifyRequiredFields();
	}
	@PrePersist void prePersist(Objectify ofy, Entity entity){
		//logger.fine(String.format("prePersist... entity: %s", entity));
		this.verifyRequiredFields();
	}
	protected void verifyRequiredFields(){
		//logger.fine(String.format("verifyRequired...%s", this));
		if(this.getDomainKey()==null){
			throw new RuntimeException(String.format("missing required field domainKey...%s", this));
		}
		if(this.getFirstName()==null || this.getFirstName().length()==0){
			throw new RuntimeException(String.format("missing required field first name...%s", this));
		}
		if(this.getLastName()==null || this.getLastName().length()==0){
			throw new RuntimeException(String.format("missing required field last name...%s", this));
		}
		if(this.getGoogleUserId()==null || this.getGoogleUserId().length()==0){
			throw new RuntimeException(String.format("missing required field google user id...%s", this));
		}
		if(this.getVersion()==null){
			throw new RuntimeException(String.format("missing required field version...%s", this));
		}
	}
}
